{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "9954668c",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "#  16\\.  分类模型评价方法  # \n",
    "\n",
    "##  16.1.  介绍  # \n",
    "\n",
    "前面的分类实验中，我们使用了准确率这一种方法对模型进行评价。实际上，分类模型的评价方法还有很多，本次实验将会了解其它常用方法以便于对分类模型评价有更全面的掌握。 \n",
    "\n",
    "##  16.2.  知识点  # \n",
    "\n",
    "  * 准确率 \n",
    "\n",
    "  * 查准率 \n",
    "\n",
    "  * 召回率 \n",
    "\n",
    "  * F1 值 \n",
    "\n",
    "  * ROC 曲线 \n",
    "\n",
    "分类模型的评价方法前面的实验中仅介绍了准确率这一种，那么接下来我们将全面了解分类模型常用的评价指标。为了更好地理解，这里将使用逻辑回归来建立信用卡持卡人风险分类预测模型。 \n",
    "\n",
    "##  16.3.  数据集介绍  # \n",
    "\n",
    "数据集为 CSV 文件，可以使用 Pandas 读取数据集并预览。 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "374a7e66",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "File 'credit_risk_train.csv' already there; not retrieving.\n",
      "\n"
     ]
    }
   ],
   "source": [
    "!wget -nc https://cdn.aibydoing.com/aibydoing/files/credit_risk_train.csv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "c961337b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>BILL_1</th>\n",
       "      <th>BILL_2</th>\n",
       "      <th>BILL_3</th>\n",
       "      <th>BILL_4</th>\n",
       "      <th>BILL_5</th>\n",
       "      <th>BILL_6</th>\n",
       "      <th>AGE</th>\n",
       "      <th>SEX</th>\n",
       "      <th>EDUCATION</th>\n",
       "      <th>MARRIAGE</th>\n",
       "      <th>RISK</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>37</td>\n",
       "      <td>Female</td>\n",
       "      <td>Graduate School</td>\n",
       "      <td>Married</td>\n",
       "      <td>LOW</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>8525</td>\n",
       "      <td>5141</td>\n",
       "      <td>5239</td>\n",
       "      <td>7911</td>\n",
       "      <td>17890</td>\n",
       "      <td>10000</td>\n",
       "      <td>25</td>\n",
       "      <td>Male</td>\n",
       "      <td>High School</td>\n",
       "      <td>Single</td>\n",
       "      <td>HIGH</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>628</td>\n",
       "      <td>662</td>\n",
       "      <td>596</td>\n",
       "      <td>630</td>\n",
       "      <td>664</td>\n",
       "      <td>598</td>\n",
       "      <td>39</td>\n",
       "      <td>Male</td>\n",
       "      <td>Graduate School</td>\n",
       "      <td>Married</td>\n",
       "      <td>HIGH</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>4649</td>\n",
       "      <td>3964</td>\n",
       "      <td>3281</td>\n",
       "      <td>934</td>\n",
       "      <td>467</td>\n",
       "      <td>12871</td>\n",
       "      <td>41</td>\n",
       "      <td>Female</td>\n",
       "      <td>Graduate School</td>\n",
       "      <td>Single</td>\n",
       "      <td>HIGH</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>46300</td>\n",
       "      <td>10849</td>\n",
       "      <td>8857</td>\n",
       "      <td>9658</td>\n",
       "      <td>9359</td>\n",
       "      <td>9554</td>\n",
       "      <td>55</td>\n",
       "      <td>Female</td>\n",
       "      <td>High School</td>\n",
       "      <td>Married</td>\n",
       "      <td>HIGH</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   BILL_1  BILL_2  BILL_3  BILL_4  BILL_5  BILL_6  AGE     SEX  \\\n",
       "0       0       0       0       0       0       0   37  Female   \n",
       "1    8525    5141    5239    7911   17890   10000   25    Male   \n",
       "2     628     662     596     630     664     598   39    Male   \n",
       "3    4649    3964    3281     934     467   12871   41  Female   \n",
       "4   46300   10849    8857    9658    9359    9554   55  Female   \n",
       "\n",
       "         EDUCATION MARRIAGE  RISK  \n",
       "0  Graduate School  Married   LOW  \n",
       "1      High School   Single  HIGH  \n",
       "2  Graduate School  Married  HIGH  \n",
       "3  Graduate School   Single  HIGH  \n",
       "4      High School  Married  HIGH  "
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "\n",
    "df = pd.read_csv(\"credit_risk_train.csv\")  # 读取数据文件\n",
    "df.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fab8469b",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "|  BILL_1  |  BILL_2  |  BILL_3  |  BILL_4  |  BILL_5  |  BILL_6  |  AGE  |  SEX  |  EDUCATION  |  MARRIAGE  |  RISK   \n",
    "---|---|---|---|---|---|---|---|---|---|---|---  \n",
    "0  |  0  |  0  |  0  |  0  |  0  |  0  |  37  |  Female  |  Graduate School  |  Married  |  LOW   \n",
    "1  |  8525  |  5141  |  5239  |  7911  |  17890  |  10000  |  25  |  Male  |  High School  |  Single  |  HIGH   \n",
    "2  |  628  |  662  |  596  |  630  |  664  |  598  |  39  |  Male  |  Graduate School  |  Married  |  HIGH   \n",
    "3  |  4649  |  3964  |  3281  |  934  |  467  |  12871  |  41  |  Female  |  Graduate School  |  Single  |  HIGH   \n",
    "4  |  46300  |  10849  |  8857  |  9658  |  9359  |  9554  |  55  |  Female  |  High School  |  Married  |  HIGH   \n",
    "  \n",
    "该数据集包含 10 列特征，以及一列类别标签。其中： \n",
    "\n",
    "  * 第 1～6 列为客户近期历史账单信息。（特征） \n",
    "\n",
    "  * 第 7 列为该客户年龄。（特征） \n",
    "\n",
    "  * 第 8 列为该客户性别。（特征） \n",
    "\n",
    "  * 第 9 列为该客户教育程度。（特征） \n",
    "\n",
    "  * 第 10 列为该客户婚姻状况。（特征） \n",
    "\n",
    "  * 第 11 列为客户持卡风险状况。（分类标签：LOW, HIGH） \n",
    "\n",
    "我们的目的，是利用该数据集训练一个信用卡持卡人风险预测模型，并对模型进行评价。首先，按照机器学习建模的流程，需要将数据集划分为训练集和测试集。 \n",
    "\n",
    "虽然上面的数据集看起来已经非常整洁，但是你会发现第 7，8，9 列的特征数据为类别型（Female / Male）。所以，这里我们在划分数据集的同时，会使用数据预处理中介绍过的独热编码将类别型特征转换为数值型特征。 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "dd774325",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Administrator\\AppData\\Local\\Temp\\ipykernel_5248\\1661365147.py:4: FutureWarning: Downcasting behavior in `replace` is deprecated and will be removed in a future version. To retain the old behavior, explicitly call `result.infer_objects(copy=False)`. To opt-in to the future behavior, set `pd.set_option('future.no_silent_downcasting', True)`\n",
      "  df.RISK = df.RISK.replace({\"LOW\": 0, \"HIGH\": 1})  # 将分类标签替换为数值，方便后面计算\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "((14000, 16), (6000, 16), (14000,), (6000,))"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.preprocessing import scale\n",
    "\n",
    "df.RISK = df.RISK.replace({\"LOW\": 0, \"HIGH\": 1})  # 将分类标签替换为数值，方便后面计算\n",
    "\n",
    "train_data = df.iloc[:, :-1]  # 特征数据列\n",
    "train_data = pd.get_dummies(train_data)  # 对特征数据进行独热编码\n",
    "train_data = scale(train_data)  # 规范化处理\n",
    "\n",
    "train_target = df[\"RISK\"]  # 目标数据列\n",
    "\n",
    "# 划分数据集，训练集占 70%，测试集占 30%\n",
    "X_train, X_test, y_train, y_test = train_test_split(\n",
    "    train_data, train_target, test_size=0.3, random_state=0\n",
    ")\n",
    "\n",
    "X_train.shape, X_test.shape, y_train.shape, y_test.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "48264583",
   "metadata": {},
   "source": [
    "**----------以下是代码解释----------**\n",
    "\n",
    "这段代码的作用是对信用卡风险数据集进行预处理和划分训练集、测试集，具体步骤如下：\n",
    "\n",
    "1. **标签数值化**  \n",
    "   ```python\n",
    "   df.RISK = df.RISK.replace({\"LOW\": 0, \"HIGH\": 1})\n",
    "   ```\n",
    "   将原本为字符串的风险标签（\"LOW\"、\"HIGH\"）转换为数值（0、1），便于后续建模。\n",
    "\n",
    "2. **特征处理**  \n",
    "   ```python\n",
    "   train_data = df.iloc[:, :-1]\n",
    "   train_data = pd.get_dummies(train_data)\n",
    "   print(train_data.head())\n",
    "   train_data = scale(train_data)\n",
    "   ```\n",
    "   - 取出除最后一列（RISK）外的所有特征数据。\n",
    "   - 对类别型特征（如性别、学历、婚姻）进行独热编码，转为数值型。\n",
    "   - 对所有特征进行标准化（均值为0，方差为1），消除量纲影响。\n",
    "\n",
    "3. **目标变量**  \n",
    "   ```python\n",
    "   train_target = df[\"RISK\"]\n",
    "   ```\n",
    "   取出标签列作为目标变量。\n",
    "\n",
    "4. **数据集划分**  \n",
    "   ```python\n",
    "   X_train, X_test, y_train, y_test = train_test_split(\n",
    "       train_data, train_target, test_size=0.3, random_state=0\n",
    "   )\n",
    "   ```\n",
    "   - 将数据集按7:3比例分为训练集和测试集，`random_state=0`保证结果可复现。\n",
    "\n",
    "5. **输出数据形状**  \n",
    "   ```python\n",
    "   X_train.shape, X_test.shape, y_train.shape, y_test.shape\n",
    "   ```\n",
    "   查看训练集和测试集的样本数和特征数。\n",
    "\n",
    "**总结**：  \n",
    "这段代码完成了数据的标签编码、特征独热编码、标准化处理，并将数据集划分为训练集和测试集，为后续模型训练和评估做准备。\n",
    "\n",
    "**----------以上是代码解释----------**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f8004fa6",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "接下来，我们使用 scikit-learn 建立逻辑回归分类模型。使用训练数据完成模型训练，并使用测试数据对模型进行评价。使用 scikit-learn 训练模型的过程非常简单，实例化相应模型的类之后，使用 ` fit()  ` 即可完成训练。 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "59808724",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>#sk-container-id-1 {\n",
       "  /* Definition of color scheme common for light and dark mode */\n",
       "  --sklearn-color-text: #000;\n",
       "  --sklearn-color-text-muted: #666;\n",
       "  --sklearn-color-line: gray;\n",
       "  /* Definition of color scheme for unfitted estimators */\n",
       "  --sklearn-color-unfitted-level-0: #fff5e6;\n",
       "  --sklearn-color-unfitted-level-1: #f6e4d2;\n",
       "  --sklearn-color-unfitted-level-2: #ffe0b3;\n",
       "  --sklearn-color-unfitted-level-3: chocolate;\n",
       "  /* Definition of color scheme for fitted estimators */\n",
       "  --sklearn-color-fitted-level-0: #f0f8ff;\n",
       "  --sklearn-color-fitted-level-1: #d4ebff;\n",
       "  --sklearn-color-fitted-level-2: #b3dbfd;\n",
       "  --sklearn-color-fitted-level-3: cornflowerblue;\n",
       "\n",
       "  /* Specific color for light theme */\n",
       "  --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
       "  --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, white)));\n",
       "  --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
       "  --sklearn-color-icon: #696969;\n",
       "\n",
       "  @media (prefers-color-scheme: dark) {\n",
       "    /* Redefinition of color scheme for dark theme */\n",
       "    --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
       "    --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, #111)));\n",
       "    --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
       "    --sklearn-color-icon: #878787;\n",
       "  }\n",
       "}\n",
       "\n",
       "#sk-container-id-1 {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 pre {\n",
       "  padding: 0;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-hidden--visually {\n",
       "  border: 0;\n",
       "  clip: rect(1px 1px 1px 1px);\n",
       "  clip: rect(1px, 1px, 1px, 1px);\n",
       "  height: 1px;\n",
       "  margin: -1px;\n",
       "  overflow: hidden;\n",
       "  padding: 0;\n",
       "  position: absolute;\n",
       "  width: 1px;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-dashed-wrapped {\n",
       "  border: 1px dashed var(--sklearn-color-line);\n",
       "  margin: 0 0.4em 0.5em 0.4em;\n",
       "  box-sizing: border-box;\n",
       "  padding-bottom: 0.4em;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-container {\n",
       "  /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
       "     but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
       "     so we also need the `!important` here to be able to override the\n",
       "     default hidden behavior on the sphinx rendered scikit-learn.org.\n",
       "     See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
       "  display: inline-block !important;\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-text-repr-fallback {\n",
       "  display: none;\n",
       "}\n",
       "\n",
       "div.sk-parallel-item,\n",
       "div.sk-serial,\n",
       "div.sk-item {\n",
       "  /* draw centered vertical line to link estimators */\n",
       "  background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
       "  background-size: 2px 100%;\n",
       "  background-repeat: no-repeat;\n",
       "  background-position: center center;\n",
       "}\n",
       "\n",
       "/* Parallel-specific style estimator block */\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item::after {\n",
       "  content: \"\";\n",
       "  width: 100%;\n",
       "  border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
       "  flex-grow: 1;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel {\n",
       "  display: flex;\n",
       "  align-items: stretch;\n",
       "  justify-content: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:first-child::after {\n",
       "  align-self: flex-end;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:last-child::after {\n",
       "  align-self: flex-start;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:only-child::after {\n",
       "  width: 0;\n",
       "}\n",
       "\n",
       "/* Serial-specific style estimator block */\n",
       "\n",
       "#sk-container-id-1 div.sk-serial {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "  align-items: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  padding-right: 1em;\n",
       "  padding-left: 1em;\n",
       "}\n",
       "\n",
       "\n",
       "/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
       "clickable and can be expanded/collapsed.\n",
       "- Pipeline and ColumnTransformer use this feature and define the default style\n",
       "- Estimators will overwrite some part of the style using the `sk-estimator` class\n",
       "*/\n",
       "\n",
       "/* Pipeline and ColumnTransformer style (default) */\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable {\n",
       "  /* Default theme specific background. It is overwritten whether we have a\n",
       "  specific estimator or a Pipeline/ColumnTransformer */\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "/* Toggleable label */\n",
       "#sk-container-id-1 label.sk-toggleable__label {\n",
       "  cursor: pointer;\n",
       "  display: flex;\n",
       "  width: 100%;\n",
       "  margin-bottom: 0;\n",
       "  padding: 0.5em;\n",
       "  box-sizing: border-box;\n",
       "  text-align: center;\n",
       "  align-items: start;\n",
       "  justify-content: space-between;\n",
       "  gap: 0.5em;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 label.sk-toggleable__label .caption {\n",
       "  font-size: 0.6rem;\n",
       "  font-weight: lighter;\n",
       "  color: var(--sklearn-color-text-muted);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 label.sk-toggleable__label-arrow:before {\n",
       "  /* Arrow on the left of the label */\n",
       "  content: \"▸\";\n",
       "  float: left;\n",
       "  margin-right: 0.25em;\n",
       "  color: var(--sklearn-color-icon);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 label.sk-toggleable__label-arrow:hover:before {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "/* Toggleable content - dropdown */\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content {\n",
       "  max-height: 0;\n",
       "  max-width: 0;\n",
       "  overflow: hidden;\n",
       "  text-align: left;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content pre {\n",
       "  margin: 0.2em;\n",
       "  border-radius: 0.25em;\n",
       "  color: var(--sklearn-color-text);\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content.fitted pre {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
       "  /* Expand drop-down */\n",
       "  max-height: 200px;\n",
       "  max-width: 100%;\n",
       "  overflow: auto;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
       "  content: \"▾\";\n",
       "}\n",
       "\n",
       "/* Pipeline/ColumnTransformer-specific style */\n",
       "\n",
       "#sk-container-id-1 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator-specific style */\n",
       "\n",
       "/* Colorize estimator box */\n",
       "#sk-container-id-1 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label label.sk-toggleable__label,\n",
       "#sk-container-id-1 div.sk-label label {\n",
       "  /* The background is the default theme color */\n",
       "  color: var(--sklearn-color-text-on-default-background);\n",
       "}\n",
       "\n",
       "/* On hover, darken the color of the background */\n",
       "#sk-container-id-1 div.sk-label:hover label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "/* Label box, darken color on hover, fitted */\n",
       "#sk-container-id-1 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator label */\n",
       "\n",
       "#sk-container-id-1 div.sk-label label {\n",
       "  font-family: monospace;\n",
       "  font-weight: bold;\n",
       "  display: inline-block;\n",
       "  line-height: 1.2em;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label-container {\n",
       "  text-align: center;\n",
       "}\n",
       "\n",
       "/* Estimator-specific */\n",
       "#sk-container-id-1 div.sk-estimator {\n",
       "  font-family: monospace;\n",
       "  border: 1px dotted var(--sklearn-color-border-box);\n",
       "  border-radius: 0.25em;\n",
       "  box-sizing: border-box;\n",
       "  margin-bottom: 0.5em;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "/* on hover */\n",
       "#sk-container-id-1 div.sk-estimator:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Specification for estimator info (e.g. \"i\" and \"?\") */\n",
       "\n",
       "/* Common style for \"i\" and \"?\" */\n",
       "\n",
       ".sk-estimator-doc-link,\n",
       "a:link.sk-estimator-doc-link,\n",
       "a:visited.sk-estimator-doc-link {\n",
       "  float: right;\n",
       "  font-size: smaller;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  border-radius: 1em;\n",
       "  height: 1em;\n",
       "  width: 1em;\n",
       "  text-decoration: none !important;\n",
       "  margin-left: 0.5em;\n",
       "  text-align: center;\n",
       "  /* unfitted */\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted,\n",
       "a:link.sk-estimator-doc-link.fitted,\n",
       "a:visited.sk-estimator-doc-link.fitted {\n",
       "  /* fitted */\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "/* Span, style for the box shown on hovering the info icon */\n",
       ".sk-estimator-doc-link span {\n",
       "  display: none;\n",
       "  z-index: 9999;\n",
       "  position: relative;\n",
       "  font-weight: normal;\n",
       "  right: .2ex;\n",
       "  padding: .5ex;\n",
       "  margin: .5ex;\n",
       "  width: min-content;\n",
       "  min-width: 20ex;\n",
       "  max-width: 50ex;\n",
       "  color: var(--sklearn-color-text);\n",
       "  box-shadow: 2pt 2pt 4pt #999;\n",
       "  /* unfitted */\n",
       "  background: var(--sklearn-color-unfitted-level-0);\n",
       "  border: .5pt solid var(--sklearn-color-unfitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted span {\n",
       "  /* fitted */\n",
       "  background: var(--sklearn-color-fitted-level-0);\n",
       "  border: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link:hover span {\n",
       "  display: block;\n",
       "}\n",
       "\n",
       "/* \"?\"-specific style due to the `<a>` HTML tag */\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link {\n",
       "  float: right;\n",
       "  font-size: 1rem;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  border-radius: 1rem;\n",
       "  height: 1rem;\n",
       "  width: 1rem;\n",
       "  text-decoration: none;\n",
       "  /* unfitted */\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link.fitted {\n",
       "  /* fitted */\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "#sk-container-id-1 a.estimator_doc_link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "</style><div id=\"sk-container-id-1\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>LogisticRegression()</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-1\" type=\"checkbox\" checked><label for=\"sk-estimator-id-1\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow\"><div><div>LogisticRegression</div></div><div><a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.6/modules/generated/sklearn.linear_model.LogisticRegression.html\">?<span>Documentation for LogisticRegression</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></div></label><div class=\"sk-toggleable__content fitted\"><pre>LogisticRegression()</pre></div> </div></div></div></div>"
      ],
      "text/plain": [
       "LogisticRegression()"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.linear_model import LogisticRegression\n",
    "\n",
    "model = LogisticRegression(solver=\"lbfgs\")  # 定义逻辑回归模型\n",
    "model.fit(X_train, y_train)  # 使用训练数据完成模型训练"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dbb8526c",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "对于分类模型而言，我们一般会使用准确率来对模型进行评价。详细来讲，通过已经训练好的模型在测试集上进行预测，从而计算出预测的准确率。 \n",
    "\n",
    "##  16.4.  准确率 Accuracy  # \n",
    "\n",
    "信用卡风险预测模型中，目标值对应了两个类别，常被称之为二分类问题。在二分类问题中，我们常常会定义正类和负类，例如这里我们定 HIGH 为 正类，LOW 为负类（你也可以反向定义）。那么，下面就可以给出实际类别（行名）和预测类别（列名）的混淆矩阵。 \n",
    "\n",
    "信用风险  |  HIGH  |  LOW   \n",
    "---|---|---  \n",
    "HIGH  |  True Positive (TP)  |  False Negative (FN)   \n",
    "LOW  |  False Positive (FP)  |  True Negative (TN)   \n",
    "  \n",
    "上表详细来讲： \n",
    "\n",
    "  * TP：将正类预测为正类数 → 预测正确 \n",
    "\n",
    "  * TN：将负类预测为负类数 → 预测正确 \n",
    "\n",
    "  * FP：将负类预测为正类数 → 预测错误 \n",
    "\n",
    "  * FN：将正类预测为负类数 → 预测遗漏 \n",
    "\n",
    "根据该混淆矩阵，我们就可以给出分类模型的常用评价指标的计算方式了。 \n",
    "\n",
    "准确率及正确分类的测试样本个数占测试实例总样本个数的比例。那么，准确率（准确度）计算公式就为： \n",
    "\n",
    "$$ Accuracy = \\frac{TP+TN}{TP+TN+FP+FN} \\tag{1} $$ \n",
    "\n",
    "当然，为了下面实现方便我们也可以将分类准确率写成下面的形式： \n",
    "\n",
    "$$ acc=\\frac{\\sum_{i=1}^{N}I(\\bar{y_{i}}=y_{i})}{N} \\tag{2} $$ \n",
    "\n",
    "式中，  $N$  表示数据总条数，  $\\bar{y_{i}}$  表示第  $i$  条数据的种类预测值，  $y_{i}$  表示第  $i$  条数据的种类真实值，  $I$  同样是指示函数，表示  $\\bar{y_{i}}$  和  $y_{i}$  相同的个数。 \n",
    "\n",
    "首先，我们需要得到模型的预测结果。这一步也非常简单，只需要使用 ` predict  ` 方法即可。 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "23868947",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 1, 1, ..., 1, 1, 1], shape=(6000,))"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_pred = model.predict(X_test)  # 输入测试集特征数据得到预测结果\n",
    "y_pred"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "67bb76dd",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'array' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mNameError\u001b[39m                                 Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[8]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[43marray\u001b[49m([\u001b[32m1\u001b[39m, \u001b[32m1\u001b[39m, \u001b[32m1\u001b[39m, ..., \u001b[32m1\u001b[39m, \u001b[32m1\u001b[39m, \u001b[32m1\u001b[39m])\n",
      "\u001b[31mNameError\u001b[39m: name 'array' is not defined"
     ]
    }
   ],
   "source": [
    "array([1, 1, 1, ..., 1, 1, 1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a206255e",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "def get_accuracy(test_labels, pred_lables):\n",
    "    # 准确率计算公式，根据公式 2 实现\n",
    "    correct = np.sum(test_labels == pred_lables)  # 计算预测正确的数据个数\n",
    "    n = len(test_labels)  # 总测试集数据个数\n",
    "    acc = correct / n\n",
    "    return acc"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b09bf64b",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "现在，只需要输入真实标签 ` y_test  ` 和模型预测标签 ` y_pred  ` 即可。 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ac62de48",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "outputs": [],
   "source": [
    "get_accuracy(y_test, y_pred)  # 计算模型预测准确率"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6e0a0795",
   "metadata": {},
   "outputs": [],
   "source": [
    "0.7678333333333334"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ed359827",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "你也可以直接使用准确率的 scikit-learn 计算方法： ` sklearn.metrics.accuracy_score(y_true,  y_pred)  ` 。 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8b15ca20",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "outputs": [],
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "accuracy_score(y_test, y_pred)  # 传入真实类别和预测类别"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3c05cd4b",
   "metadata": {},
   "outputs": [],
   "source": [
    "0.7678333333333334"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8cb22b7c",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "实际上，scikit-learn 建模时也可以直接使用 ` model.score()  ` 求得分类准确率： "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "11e6f3ba",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "outputs": [],
   "source": [
    "model.score(X_test, y_test)  # 传入测试数据特征和类别"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bc084872",
   "metadata": {},
   "outputs": [],
   "source": [
    "0.7678333333333334"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1908d6e6",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "上面，我们就说完了常用的 3 种分类准确率计算方法。分类模型作为机器学习中最常遇到的建模问题，除了使用「准确率」对模型进行评价，实际上还有另外几种常用的性能评价指标，在此一并介绍。 \n",
    "\n",
    "##  16.5.  查准率 Precision  # \n",
    "\n",
    "查准率又称精确率，即正确分类的正例个数占分类为正例的实例个数的比例。 \n",
    "\n",
    "$$Precision = \\frac{TP}{TP+FP} \\tag{3}$$ \n",
    "\n",
    "查准率的 scikit-learn 计算方法： ` sklearn.metrics.precision_score(y_true,  y_pred)  ` 。 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3b5bb8ff",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "outputs": [],
   "source": [
    "from sklearn.metrics import precision_score\n",
    "\n",
    "precision_score(y_test, y_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c740e57d",
   "metadata": {},
   "outputs": [],
   "source": [
    "0.7678333333333334"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b2b4c170",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "##  16.6.  召回率 Recall  # \n",
    "\n",
    "召回率又称查全率，即正确分类的正例个数占实际正例个数的比例。 \n",
    "\n",
    "$$Recall = \\frac{TP}{TP+FN} \\tag{4}$$ \n",
    "\n",
    "召回率的 scikit-learn 计算方法： ` sklearn.metrics.recall_score(y_true,  y_pred)  ` 。 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8c3bfeca",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "outputs": [],
   "source": [
    "from sklearn.metrics import recall_score\n",
    "\n",
    "recall_score(y_test, y_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ee35b5ca",
   "metadata": {},
   "outputs": [],
   "source": [
    "1.0"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dd8aa91d",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "##  16.7.  F1 值  # \n",
    "\n",
    "F1 值是查准率和召回率的加权平均数 \n",
    "\n",
    "$$F1 = \\frac{2*(Precision * Recall)}{Precision + Recall} \\tag{5}$$ \n",
    "\n",
    "F1 相当于精确率和召回率的综合评价指标，对衡量数据更有利，也比较常用。 \n",
    "\n",
    "F1 值的 scikit-learn 计算方法： ` sklearn.metrics.f1_score(y_true,  y_pred)  ` 。 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b5ae4e22",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "outputs": [],
   "source": [
    "from sklearn.metrics import f1_score\n",
    "\n",
    "f1_score(y_test, y_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2b6f2f29",
   "metadata": {},
   "outputs": [],
   "source": [
    "0.8686716319411709"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a6b93992",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "##  16.8.  ROC 曲线  # \n",
    "\n",
    "部分分类模型中（如：逻辑回归），通常会设定一个阈值，并规定大于该阈值为正类，小于则为负类。所以，当我们减小阀值时，将会有更多的样本被划分到正类。这样会提高正类的识别率，但同时也会使得更多的负类被错误识别为正类。 \n",
    "\n",
    "所以，ROC 曲线的目的在用形象化该变化过程，从而评价一个分类器好坏。 \n",
    "\n",
    "ROC 曲线中有两个指标，分别是 TPR 和 FPR，公式如下： \n",
    "\n",
    "$$TPR = \\frac{TP}{TP+FN} \\tag{6a}$$ \n",
    "\n",
    "$$FPR = \\frac{FP}{FP+TN} \\tag{6b}$$ \n",
    "\n",
    "其中，TPR 代表能将正例分对的概率（召回率），而 FPR 则代表将负例错分为正例的概率。 \n",
    "\n",
    "ROC 曲线中，我们将横轴定为 FPR，纵轴定为 TPR，从而可以直观看出 FPR 与 TPR 之间的关系。 \n",
    "\n",
    "![image](https://cdn.aibydoing.com/aibydoing/images/document-uid214893labid7506timestamp1540448403508.svg)\n",
    "\n",
    "[ 来源 ](https://en.wikipedia.org/wiki/Receiver_operating_characteristic)\n",
    "\n",
    "那么： \n",
    "\n",
    "  * 当 FPR=0，TPR=0 时，意味着将每一个实例都预测为负例。 \n",
    "\n",
    "  * 当 FPR=1，TPR=1 时，意味着将每一个实例都预测为正例。 \n",
    "\n",
    "  * 当 FPR=0，TPR=1 时，意味着为最优分类器点。 \n",
    "\n",
    "那么，一个优秀分类器对应的 ROC 曲线应该尽量靠近左上角。当曲线越接近于 45 度对角线，则分类器效果越差。 \n",
    "\n",
    "ROC 曲线的 scikit-learn 计算方法： ` sklearn.metrics.roc_curve(y_true,  y_score)  ` 。 \n",
    "\n",
    "虽然使用 ROC 曲线来表示分类器好坏很直观，但人们往往更喜欢使用数值来评价分类器，此时就提出了 AUC 的概念。AUC 的全称为 Area Under Curve，意思是曲线下面积，即 ROC 曲线下面积。 \n",
    "\n",
    "  * $AUC=1$  ：完美分类器。 \n",
    "\n",
    "  * $0.5<AUC<1$  ：分类器优于随机猜测。 \n",
    "\n",
    "  * $AUC=0.5$  ：分类器和随机猜测的结果接近。 \n",
    "\n",
    "  * $AUC<0.5$  ：分类器比随机猜测的结果还差。 \n",
    "\n",
    "AUC 的 scikit-learn 计算方法： ` sklearn.metrics.auc(fpr,  tpr)  ` 。 \n",
    "\n",
    "下面，我们就绘制出本次预测结果的 ROC 曲线： "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "58c2c11c",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x177acb2d310>"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from matplotlib import pyplot as plt\n",
    "\n",
    "%matplotlib inline\n",
    "\n",
    "from sklearn.metrics import roc_curve\n",
    "from sklearn.metrics import auc\n",
    "\n",
    "y_score = model.decision_function(X_test)\n",
    "fpr, tpr, _ = roc_curve(y_test, y_score)\n",
    "roc_auc = auc(fpr, tpr)\n",
    "\n",
    "plt.plot(fpr, tpr, label=\"ROC curve (area = %0.2f)\" % roc_auc)\n",
    "plt.plot([0, 1], [0, 1], color=\"navy\", linestyle=\"--\")\n",
    "plt.xlabel(\"False Positive Rate\")\n",
    "plt.ylabel(\"True Positive Rate\")\n",
    "plt.legend()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a7ac1ce6",
   "metadata": {},
   "source": [
    "当前单元格的代码如下：\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "324e853d",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.metrics import precision_score\n",
    "\n",
    "precision_score(y_test, y_pred)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0a301818",
   "metadata": {},
   "source": [
    "**----------以下是代码解释----------**\n",
    "\n",
    "### 代码解释：\n",
    "1. **`from sklearn.metrics import precision_score`**:\n",
    "   - 从 `scikit-learn` 的 `metrics` 模块中导入 `precision_score` 函数。\n",
    "   - 该函数用于计算分类模型的查准率（Precision），即预测为正类的样本中实际为正类的比例。\n",
    "\n",
    "2. **`precision_score(y_test, y_pred)`**:\n",
    "   - `y_test`: 测试集的真实标签。\n",
    "   - `y_pred`: 模型对测试集的预测标签。\n",
    "   - 该函数会根据输入的真实标签和预测标签，计算查准率的值，公式为：\n",
    "     $$ Precision = \\frac{TP}{TP + FP} $$\n",
    "   - 其中：\n",
    "     - `TP`（True Positive）：被正确预测为正类的样本数。\n",
    "     - `FP`（False Positive）：被错误预测为正类的样本数。\n",
    "\n",
    "### 输出：\n",
    "执行该代码后，将返回模型在测试集上的查准率（Precision）值，用于评价模型在正类预测上的准确性。\n",
    "\n",
    "**----------以上是代码解释----------**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "46eb6568",
   "metadata": {},
   "source": [
    "\n",
    "##  16.9.  总结  # \n",
    "\n",
    "本次实验介绍了分类预测后常用的几个评价指标，它们分别是：准确率，查准率，召回率，F1 值，ROC 曲线。对于这几种方法，接下来要多做练习并熟练掌握。 "
   ]
  }
 ],
 "metadata": {
  "jupytext": {
   "cell_metadata_filter": "-all",
   "main_language": "python",
   "notebook_metadata_filter": "-all"
  },
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
